package caidan;

import caidan.data.CategoryData;
import caidan.data.FoodData;
import jinyilw.common.Operator;
import jinyilw.common.TextTools;
import jinyilw.common.math.MathTools;
import jinyilw.swing.FontTools;
import jinyilw.swing.visuals.Rcomp.RButton;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;

public class OneMealPanel extends JComponent
{
	private static final long serialVersionUID = 4585062742700169968L;
	private static final String lineStr = TextTools.lineString();
	private final int[][] data;
	private final FoodData[] foodDatas;
	private final FFPanel[] ffPanels;
	private final OneDayPanel oneDayPanel;
	private final JLabel mealLabel;
	private final String mealStr;
	private final int dayIndex;
	private final int mealIndex;
	private final StringBuilder saveStr;
	StringBuilder mainFood, sideFood;
	private RButton editButton;
	PositionConfiger positionConfiger;
	private boolean editable = false;
	private final boolean isBreakfast;
	private final int maxChooseNum;
	private final int[] chooseNums;

	private final CategoryData[] categoryDatas;

	public OneMealPanel(int m, OneDayPanel oneDayPanel)
	{
		mealIndex = m;
		this.oneDayPanel = oneDayPanel;
		dayIndex = oneDayPanel.dayIndex;
		positionConfiger = oneDayPanel.positionConfiger;
		isBreakfast = m == 0;
		chooseNums = isBreakfast
				? MainApp.breakfastChooseNums
				: MainApp.otherChooseNums;
		maxChooseNum = isBreakfast
				? MainApp.breakfastMaxChooseNum
				: MainApp.otherMaxChooseNum;

		categoryDatas = MainApp.getCategoryDatas();
		data = new int[categoryDatas.length][];
		for (int i = 0; i < data.length; i++)
		{
			data[i] = new int[chooseNums[i]];
			for (int j = 0; j < data[i].length; j++)
				data[i][j] = -1;
		}
		foodDatas = new FoodData[maxChooseNum];
		ffPanels = new FFPanel[maxChooseNum];
		for (int i = 0; i < ffPanels.length; i++)
			ffPanels[i] = new FFPanel(positionConfiger, this);

		setLayout(null);
		mealStr = MainApp.mealStrings[m];
		mealLabel = new JLabel(mealStr);
		mealLabel.setFont(FontTools.getCustomFont(16));
		mealLabel.setHorizontalAlignment(SwingConstants.CENTER);
		add(mealLabel);
		LagerOperator lagerOperator = new LagerOperator();
		for (int i = 0; i < ffPanels.length; i++)
		{
			if (i < maxChooseNum)
				add(ffPanels[i]);
			ffPanels[i].addMouseListener(lagerOperator);
		}
		saveStr = new StringBuilder();
		mainFood = new StringBuilder();
		sideFood = new StringBuilder();
	}

	public void setEditable(boolean editable)
	{
		if (this.editable == editable)
			return;
		this.editable = editable;
		if (editable)
		{
			if (editButton == null)
			{
				createEditButton();
			}
			add(editButton);
		} else
		{
			for (int i = MainApp.categoryNames.length; i < MainApp.categoryNames.length; i++)
				for (int j = 0; j < data[i].length; j++)
					data[i][j] = -1;
			remove(editButton);
		}
	}

	private void createEditButton()
	{
		editButton = new RButton("编辑");
		editButton.addActionListener((ActionEvent e) ->
		{
			EditerDialog editerDialog = getEditer(isBreakfast);
			editerDialog.setCurrentMeal(this);
			editerDialog.setVisible(true);
		});
	}

	@Override
	public void setBounds(int x, int y, int width, int height)
	{
		super.setBounds(x, y, width, height);
		if (positionConfiger == null)
			return;
		mealLabel.setBounds(8,
				(positionConfiger.getH() + positionConfiger.getS() - 15) / 2
						- 8,
				40, 30);
		int xx = 50;
		for (int i = 0; i < ffPanels.length; i++)
		{
			ffPanels[i].setBounds(xx, 0, positionConfiger.getW(),
					positionConfiger.getH());
			xx = xx + positionConfiger.getW() + positionConfiger.getS();
		}
		xx = width - positionConfiger.getH() - positionConfiger.getS() - 10;
		if (editable && editButton != null)
			editButton.setBounds(xx, 3, positionConfiger.getH(),
					positionConfiger.getH() - 6);
	}

	public void setFoodDatas(ArrayList<FoodData> foodDatas)
	{
		for (int i = 0; i < ffPanels.length; i++)
		{
			ffPanels[i].setFoodData(foodDatas.get(i));
		}
	}

	public void updateMeal()
	{
		if (saveStr.length() > 0)
			saveStr.delete(0, saveStr.length() - 1);
		int ii = 0;
		if (isEmpty())
		{
			for (; ii < foodDatas.length; ii++)
				foodDatas[ii] = null;
		} else
		{
			ArrayList<FoodData> list;
			for (int i = 0; i < data.length; i++)
			{
				list = categoryDatas[i].getCurrentDatas(isBreakfast);
				int size = list.size();
				for (int j = 0; j < data[i].length; j++)
				{
					foodDatas[ii] = (data[i][j] == -1 || data[i][j] >= size)
							? null
							: list.get(data[i][j]);
					ii++;
				}
			}
			saveStr.append(mealStr).append(":");
		}

		if (mainFood.length() > 0)
			mainFood.delete(0, mainFood.length() - 1);
		if (sideFood.length() > 0)
			sideFood.delete(0, sideFood.length() - 1);
		String name;
		for (int i = 0; i < foodDatas.length; i++)
		{
			ffPanels[i].setFoodData(foodDatas[i]);
			if (foodDatas[i] != null)
			{
				name = foodDatas[i].getFoodName();
				saveStr.append(name).append(",");
				if (foodDatas[i].isMainFood())
					mainFood.append(name).append(lineStr);
				else
					sideFood.append(name).append(lineStr);
			}
		}
		if (saveStr.length() > 0)
			saveStr.deleteCharAt(saveStr.length() - 1);
		saveStr.append(lineStr);
		if (mainFood.length() > 0)
			mainFood.deleteCharAt(mainFood.length() - 1);
		if (sideFood.length() > 0)
			sideFood.deleteCharAt(sideFood.length() - 1);
	}

	public boolean isEmpty()
	{
		for (int i = 0; i < data.length; i++)
			for (int j = 0; j < data[i].length; j++)
				if (data[i][j] != -1)
					return false;
		return true;
	}

	public void setToRandom()
	{
		int size;
		for (int i = 0; i < categoryDatas.length; i++)
		{
			size = categoryDatas[i].getCurrentDatas(isBreakfast).size();
			if (size > 0 && data[i].length > 0)
				data[i] = MathTools.getRandomDifferInts(size, data[i].length);
			else
				for (int j = 0; j < data[i].length; j++)
					data[i][j] = -1;
		}
		updateMeal();
	}

	public int[][] getData()
	{
		return data;
	}

	public void setData(int[][] d)
	{
		for (int i = 0; i < d.length; i++)
			for (int j = 0; j < d[i].length; j++)
				data[i][j] = d[i][j];
	}

	public String getSaveStr()
	{
		return saveStr.toString();
	}

	public FoodData[] getFoodDatas()
	{
		return foodDatas;
	}

	public int getDay()
	{
		return dayIndex;
	}

	public int getMeal()
	{
		return mealIndex;
	}

	public void writeData(DataOutputStream dos) throws IOException
	{
		for (FoodData data : foodDatas)
		{
			if (data != null)
				dos.writeUTF(data.getFoodName());
			else
				dos.writeUTF("null");
		}
	}

	public void readData(DataInputStream dis, int appVersion) throws IOException
	{
		if (appVersion > 100)
		{
			ArrayList<FoodData> list;
			String name;
			for (int i = 0; i < categoryDatas.length; i++)
			{
				list = categoryDatas[i].getCurrentDatas(isBreakfast);
				for (int j = 0; j < data[i].length; j++)
				{
					name = dis.readUTF();
					if ("null".equals(name))
						data[i][j] = -1;
					else
						data[i][j] = FoodData.getIndex(list, name);
				}
			}

		} else
			for (int i = 0; i < data.length; i++)
				for (int j = 0; j < data[i].length; j++)
					data[i][j] = dis.readInt();
	}

	public MealLagerView getMealLagerView()
	{
		return oneDayPanel.getOneWeekView().getMealLagerView();
	}

	public EditerDialog getEditer(boolean isBreakfast)
	{
		if (isBreakfast)
			return oneDayPanel.getOneWeekView().getBreakfastEditer();
		return oneDayPanel.getOneWeekView().getOtherMealEditer();
	}

	private class LagerOperator extends MouseAdapter
	{
		@Override
		public void mouseClicked(MouseEvent e)
		{
			Object o = e.getSource();
			int index = 0;
			if (o instanceof FFPanel)
			{
				FFPanel cp = (FFPanel) o;
				if (cp.getFoodData() == null)
					return;
				cp.updateImage();
				for (index = 0; index < ffPanels.length; index++)
					if (cp == ffPanels[index])
						break;
				MealLagerView mealLagerView = getMealLagerView();
				mealLagerView.setLagerView(OneMealPanel.this, index);
				mealLagerView.setVisible(true);
			}
		}
	}
}

class FFPanel extends FoodComp
{
	private static final long serialVersionUID = -4176814257157670761L;
	// private OneMealPanel mealPanel;
	private final Operator<String> nameChangedOperator;

	public FFPanel(PositionConfiger p, OneMealPanel mealPanel)
	{
		super(p);
		// this.mealPanel = mealPanel;
		nameChangedOperator = (String o) ->
		{
			foodNameLabel.setText(o);
		};
	}

	public void setFoodData(FoodData newData)
	{
		if (foodData == newData)
			return;
		if (foodData != null)
			foodData.removeNameChangedOperater(nameChangedOperator);
		if (newData != null)
		{
			setImage(newData.getThumbnail());
			foodNameLabel.setText(newData.getFoodName());
			newData.addNameChangedOperater(nameChangedOperator);
		} else
		{
			setImage(null);
			foodNameLabel.setText("");
		}
		foodData = newData;
	}

	//	public void setFoodData(FoodData foodData, boolean isTotalCount)
	//	{
	//		this.foodData = foodData;
	//		if (foodData != null)
	//		{
	//			setImage(foodData.getThumbnail());
	//			int n = isTotalCount
	//					? foodData.getTotalCount()
	//					: foodData.getCount(mealPanel.getDay(),
	//							mealPanel.getMeal());
	//			String text = foodData.getFoodName();
	//			if (n > 0)
	//				text += "(" + n + ")";
	//			foodNameLabel.setText(text);
	//		} else
	//		{
	//			setImage(null);
	//			foodNameLabel.setText("");
	//		}
	//	}

	@Override
	public FoodData getFoodData()
	{
		return foodData;
	}

	public void updateImage()
	{
		if (getImage() == null)
			setImage(foodData.getThumbnail());
	}
}
